<?php 

declare(strict_types=1);

namespace WanZ\App\Utils\Prometheus;

use Prometheus\CollectorRegistry;
use Prometheus\Exception\MetricsRegistrationException;
use Prometheus\Histogram;
use Prometheus\RenderTextFormat;
use Prometheus\Storage\Redis;
use Prometheus\Summary;
use Throwable;
use Hyperf\Contract\StdoutLoggerInterface;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Utils\ApplicationContext;
use Hyperf\HttpServer\Contract\RequestInterface;
use MoChat\Framework\Constants\ErrorCode;
use MoChat\Framework\Exception\CommonException;

/**
 * Class Prometheus
 * @package WanZ\App\Utils\Prometheus
 */
abstract class Prometheus
{
    private static $instance = null;

    /**
     * @Inject
     * @var StdoutLoggerInterface
     */
    private $logger;

    /**
     * 获取度量指标
     * @return string
     */
    protected function getMetrics(): string
    {
        return (new RenderTextFormat())->render(self::getCollectorRegistry()->getMetricFamilySamples());
    }

    /**
     * 获取请求的公司ID和用户类型
     * @return array
     */
    protected function getCompanyIdAndUType(): array
    {
        return [
            'company_id' => (int) ApplicationContext::getContainer()->get(RequestInterface::class)->input('company_id', 0),
            'u_type' => (int) ApplicationContext::getContainer()->get(RequestInterface::class)->input('u_type', 0),
        ];
    }

    /**
     * 添加度量指标 addMetrics
     *
     * @param string $namespace
     * @param string $name
     * @param string $help
     * @param array $labels
     * @param int $inc
     */
    protected function incBy(string $namespace, string $name, string $help, array $labels = [], int $inc = 1)
    {
        $labelKeys = $labelValues = [];
        foreach ($labels as $labelKey => $labelValue) {
            $labelKeys[] = $labelKey;
            $labelValues[] = $labelValue;
        }

        try {
            self::getCollectorRegistry()
                ->getOrRegisterCounter($namespace, $name, $help, $labelKeys)
                ->incBy($inc, $labelValues);
        } catch (Throwable $exception) {
            $this->logger->error('prometheusError', [
                'errorMsg'=> $exception->getMessage(),
                'site' => $exception->getFile() .'|'. $exception->getLine()
            ]);
        }
    }

    /**
     * 统计接口的响应时间
     *
     * @param string $namespace
     * @param string $name
     * @param string $help
     * @param array $labels
     * @param array|null $quantiles
     * @return Histogram
     * @throws MetricsRegistrationException
     * @throws Throwable
     */
    protected function histogram(string $namespace, string $name, string $help, array $labels = [], array $quantiles = null): Histogram
    {
        try {
            return self::getCollectorRegistry()
                ->getOrRegisterHistogram($namespace, $name, $help, $labels, $quantiles);
        } catch (Throwable $exception) {
            $this->logger->error('initHistogramError', [
                'errorMsg' => $exception->getMessage(),
                'site'     => $exception->getFile() .'|'. $exception->getLine(),
                'value'    => json_encode([$namespace, $name, $help, $labels, $quantiles])
            ]); 
            throw $exception;
        }
    }

    /**
     * 获取实例
     * @return CollectorRegistry
     */
    private static function getCollectorRegistry(): CollectorRegistry
    {
        if (self::$instance instanceof CollectorRegistry) {
            return self::$instance;
        }

       self::$instance = new CollectorRegistry(new MetricsToCustomRedis(), false);
       return self::$instance;
    }
}

